#include "stdafx.h"
#include "Nervus.h"


CNervus::CNervus(CNervusAntenna* pIn, CNervusAntenna* pOut)
{
	pNextInLine = NULL;
	m_pFirstInputNervusAntenna = pIn;
	m_pFirstOutputNervusAntenna = pOut;
	if( pIn )
		pIn->SetMyNervus( this );
	if( pOut )
		pOut->SetMyNervus( this );
	m_bExcited = false;
	m_nExcitedCount = 0;
	m_nSavedSignal = 0;
	m_bRestrain = false;
	m_nRestrainCount = 0;
}


CNervus::~CNervus(void)
{
	if( pNextInLine )
		delete pNextInLine;
	if( m_pFirstInputNervusAntenna )
		delete m_pFirstInputNervusAntenna;
	if( m_pFirstOutputNervusAntenna )
		delete m_pFirstOutputNervusAntenna;
}

void CNervus::ProcessSignal( void )
{
	CNervusAntenna* pAntenna = GetFirstInputAntenna();
	int nSignal = pAntenna->GetSignal();
	while( pAntenna = pAntenna->GetNextAntenna() )
	{
		nSignal += pAntenna->GetSignal();
		//if( GetPosition().nLine == 3 && GetPosition().nIdx == 0 )
		//	TRACE("%d , ", nSignal );
	};

	m_nSavedSignal += nSignal;
	//if( GetPosition().nLine == 3 && GetPosition().nIdx == 0 )
	//	TRACE("--[%d,%d], save %d, ex_count=%d, re_count=%d\n", GetPosition().nLine, GetPosition().nIdx, m_nSavedSignal,m_nExcitedCount,m_nRestrainCount);

	if( !m_bExcited && !m_bRestrain )
	{
		if( m_nSavedSignal >= SIGNAL_BASE )
		{
			m_bExcited = true;
			m_nExcitedCount = 0;
			m_nSavedSignal -= SIGNAL_BASE;
			//TRACE("exciting! [%d,%d], save %d\n", GetPosition().nLine, GetPosition().nIdx, m_nSavedSignal);
		}
		else if( m_nSavedSignal <= -SIGNAL_BASE )
		{
			m_bRestrain = true;
			m_nRestrainCount = 0;
			m_nSavedSignal += SIGNAL_BASE;
			//TRACE("Restrain! [%d,%d], save %d\n", GetPosition().nLine, GetPosition().nIdx, m_nSavedSignal);
		}
	}

	if( m_bExcited )
	{
		if( m_nExcitedCount++ == 0 )
		{
			pAntenna = GetFirstOutputAntenna();
			do
			{
				pAntenna->SetSignal( SIGNAL_BASE );
			}while( pAntenna = pAntenna->GetNextAntenna() );
		}
		else
		{
			if( m_nSavedSignal > (SIGNAL_PERIOD-m_nExcitedCount)*SIGNAL_BASE )
			{
				m_nSavedSignal -= (SIGNAL_PERIOD-m_nExcitedCount)*SIGNAL_BASE;
				m_nExcitedCount == 1;
				pAntenna = GetFirstOutputAntenna();
				do
				{
					pAntenna->SetSignal( SIGNAL_BASE );
				}while( pAntenna = pAntenna->GetNextAntenna() );
			}
			else
			{
				pAntenna = GetFirstOutputAntenna();
				do
				{
					pAntenna->SetSignal( SIGNAL_ZERO );
				}while( pAntenna = pAntenna->GetNextAntenna() );
			}

			if( m_nExcitedCount == SIGNAL_PERIOD )
			{
				m_nExcitedCount = 0;
				m_bExcited = false;
			}
		}
	}
	else if( m_bRestrain )
	{
		if( m_nRestrainCount++ == 0 )
		{
			pAntenna = GetFirstOutputAntenna();
			do
			{
				pAntenna->SetSignal( -SIGNAL_BASE );
			}while( pAntenna = pAntenna->GetNextAntenna() );
		}
		else
		{
			if( m_nSavedSignal < (SIGNAL_PERIOD-m_nRestrainCount)*SIGNAL_BASE )
			{
				m_nSavedSignal += (SIGNAL_PERIOD-m_nRestrainCount)*SIGNAL_BASE;
				m_nExcitedCount == 1;
				pAntenna = GetFirstOutputAntenna();
				do
				{
					pAntenna->SetSignal( -SIGNAL_BASE );
				}while( pAntenna = pAntenna->GetNextAntenna() );
			}
			else
			{
				pAntenna = GetFirstOutputAntenna();
				do
				{
					pAntenna->SetSignal( SIGNAL_ZERO );
				}while( pAntenna = pAntenna->GetNextAntenna() );
			}
			if( m_nRestrainCount == SIGNAL_PERIOD )
			{
				m_bRestrain = false;
				m_nRestrainCount = 0;
			}
		}
	}
	else
	{
		pAntenna = GetFirstOutputAntenna();
		do
		{
			pAntenna->SetSignal( SIGNAL_ZERO );
		}while( pAntenna = pAntenna->GetNextAntenna() );
	}
}

void CNervus::DoSignalTransmition( void )
{
//	if( GetPosition().nLine == 2 && GetPosition().nIdx == 26 )
//		TRACE(".\n");
	CNervusAntenna* pAntenna = GetFirstOutputAntenna();
	do
	{
		pAntenna->TransmitSignal();
	}while( pAntenna = pAntenna->GetNextAntenna() );
}

void CNervusNet::ProcessSignal( void )
{
	for( int j=0; j<NERVUS_NET_DEPTH; j++ )
	{
		CNervus *pNervus = m_pNervusLines[j];
		do
		{
			pNervus->ProcessSignal();
		}while( pNervus=pNervus->pNextInLine );
	}

	for( int j=0; j<NERVUS_NET_DEPTH; j++ )
	{
		CNervus *pNervus = m_pNervusLines[j];
		do
		{
			pNervus->DoSignalTransmition();
		}while( pNervus=pNervus->pNextInLine );
	}

	//TRACE("\n");
}
